#include "core.h"
#include "IList.h"

// ....................................................................................................................
// Konstruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IList::IList(void) {
	Items = NULL; Count = Capacity = 0; // Inicializacia
}
// ....................................................................................................................
// ....................................................................................................................
// Destruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IList::~IList(void) {
	Clear(); // Uvolnim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Uvolnenie objektu z pamate
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IList::Clear(void) {
	if (Items != NULL) delete Items; // Zrusim pamat
	Items = NULL; Count = Capacity = 0; // Inicializacia
}
// ....................................................................................................................
// ....................................................................................................................
// Alokacia pamate podla potreby
// Vstup:
//			pCapacity - pozadovana kapacita
//			pCopy - priznak skopirovania aktualneho obsahu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IList::Allocate(INT32 pCapacity, bool pCopy) {
	if (Capacity >= pCapacity) return; // Treba alokovat?
	Capacity = ALIGN2048(pCapacity); // Urcim novu kapacitu
	PVOID *NW = new PVOID[Capacity]; // Alokujem novu pamat
	if (Items != NULL) { // Je nejaky obsah?
		if ((Count > 0) && (pCopy)) memcpy(NW, Items, Count * sizeof(PVOID)); // Ak je poziadavka tak skopirujem aktualny obsah
		delete Items; // Zrusim aktualny obsah
	}
	Items = NW; // Ulozim novu pamat
}
// ....................................................................................................................
// ....................................................................................................................
// Zaradenie hodnoty na koniec zoznamu
// Vstup:
//			pValue - hodnota na zaradenie do zoznamu
// Vystup:
//			pozicia noveho zaznamu
// ....................................................................................................................
INT32 __fastcall IList::Add(PVOID pValue) {
	Allocate(Count + 1, true); // Alokujem pamat
	INT32 C = Count++; // Zvysim pocet
	Items[C] = pValue; // Ulozim na koniec
	return C; // Vratim poziciu
}
// ....................................................................................................................
// ....................................................................................................................
// Vlozenie hodnoty do zoznamu na zadanu poziciu
// Vstup:
//			pIndex - pozicia pre vlozenie
//			pValue - hodnota na vlozenie do zoznamu
// Vystup:
//			pozicia noveho zaznamu
// ....................................................................................................................
INT32 __fastcall IList::Insert(INT32 pIndex, PVOID pValue) {
	if (!ICore::IsValidIndex(pIndex, 0, Count)) return Add(pValue); // Neplatny index? Pridam na koniec
	Allocate(Count + 1, true); // Alokujem pamat
	memmove(Items + pIndex + 1, Items + pIndex, (Count - pIndex) * sizeof(PVOID)); // Presuniem a urobim miesto
	Items[pIndex] = pValue; // Ulozim hodnotu
	Count++; // Zvysim pocet zaznamov
	return pIndex; // Vratim index
}
// ....................................................................................................................
// ....................................................................................................................
// Vymazanie zaznamu
// Vstup:
//			pIndex - pozicia pre vlozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IList::Delete(INT32 pIndex) {
	if (!ICore::IsValidIndex(pIndex, 0, Count)) return; // Test platnosti indexu
	if (pIndex != Count - 1) memmove(Items + pIndex, Items + pIndex + 1, (Count - pIndex - 1) * sizeof(PVOID)); // Presuniem a zrusim zaznam
	Count--; // Znizim pocet zaznamov
}
// ....................................................................................................................
// ....................................................................................................................
// Triedenie zoznamu
// Vstup:
//			pCompareFnc - porovnavacia funkcia
//			pStart - zaciatok
//			pCount - pocet
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IList::Sort(INT32(__cdecl *pCompareFnc)(CONST_PVOID, CONST_PVOID), INT32 pStart, INT32 pCount) {
	if (!ICore::IsValidIndex(pStart, 0, Count)) return; // Platny zaciatok?
	INT32 C = pCount == -1 ? Count : pCount;
	if (pStart + C > Count) C = Count - pStart; // Urcim pocet
	qsort(Items + pStart, C, sizeof(PVOID), pCompareFnc); // Volam triedenie
}
// ....................................................................................................................
// ....................................................................................................................
// Skopirovanie obsahu objektu
// Vstup:
//			pValue - objekt pre skopirovanie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IList::Assign(IList *pValue) {
	if (pValue->Count == 0) Clear();
	else {
		Allocate(pValue->Count, false); // Alokujem pamat
		memcpy(Items, pValue->Items, pValue->Count * sizeof(PVOID)); // Skopirujem obsah
		Count = pValue->Count;
	}
}
// ....................................................................................................................
